using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Identity.Application.Contracts.Services;
using Identity.Application.PermissionKeyResourceIds.Interfaces;
using Identity.Application.RolePermissions.Interfaces;
using Identity.Application.Users.Commands;
using MediatR;
using Microsoft.IdentityModel.JsonWebTokens;

namespace Identity.Application.Users.CommandHandler;

public class AuthorizeCommandHandler : IRequestHandler<AuthorizeCommand, List<Claim>>
{
    private readonly ITokenService _tokenService;
    private readonly IRedisService _redisService;
    private readonly IUserService _userService;

    private readonly IRoleService _roleService;

    private readonly IRolePermissionsReadService _rolePermissionsReadService;
    private readonly IApiPermissionBindingReadService _permissionKeyResourceIdRepository;

    public AuthorizeCommandHandler(
        ITokenService tokenService,
        IRedisService redisService,
        IUserService userService,
        IRoleService roleService,
        IRolePermissionsReadService rolePermissionsReadService,
        IApiPermissionBindingReadService permissionKeyResourceIdRepository
        )
    {
        _tokenService = tokenService;
        _redisService = redisService;
        _userService = userService;
        _roleService = roleService;
        _rolePermissionsReadService = rolePermissionsReadService;
        _permissionKeyResourceIdRepository = permissionKeyResourceIdRepository;

    }

    public async Task<List<Claim>> Handle(AuthorizeCommand request, CancellationToken cancellationToken)
    {


        // 从 Redis 验证临时 token 是否有效
        var princ = _tokenService.ValidateToken(request.tempToken);
        if (princ == null) throw new Exception("解析登录token失败");

        var nonce = princ.FindFirst("nonce")?.Value;
        if (string.IsNullOrEmpty(nonce)) throw new Exception("验证参数不存在");

        // 检查 Redis 是否存在
        var exists = await _redisService.GetStringAsync($"login_nonce:{nonce}");
        if (exists == null) throw new Exception("解析登录token已使用或无效"); ; // 已使用或无效


        // 一次性使用
        await _redisService.DeleteKeyAsync($"login_nonce:{nonce}");
        var userId = princ.FindFirst(JwtRegisteredClaimNames.Sub)?.Value
          ?? princ.FindFirst(ClaimTypes.NameIdentifier)?.Value;

        if (!Guid.TryParse(userId, out Guid guid)) throw new Exception("用户Id格式不正确"); ;

        // 4. 构造 OpenIddict 的 principal
        var name = princ.FindFirst("name")?.Value;

        var tempClaims = new List<Claim>
        {
            new Claim("sub", userId!),
            new Claim("name", name ?? userId!)
        };

        var user = await _userService.GetUserByIdAsync(guid);
        if (user == null) throw new Exception("解析用户不存在失败"); ;
        var roles = user.Roles;
        foreach (var roleName in roles)
        {
            tempClaims.Add(new Claim("role", roleName));

            var role = await _roleService.GetRoleByNameAsync(roleName);
            
            if (role != null)
            {
                var RolePermissions = await _rolePermissionsReadService.GetRolePermissions();
                var perms = RolePermissions
                    .Where(rp => rp.RoleId == role.Id)
                    .Select(rp => rp.Permission?.Key)
                    .ToList();

                foreach (var p in perms)
                {
                    if (p == null || tempClaims.Any(a => a.Value == p)) continue;
                    if (await _permissionKeyResourceIdRepository.IsUserCenterPermissionAsync(p)) continue;
                    tempClaims.Add(new Claim("permission", p));
                }

            }
        }

        return tempClaims;

    }
}